<template>
  <div class="flex flex-col">
    <div class="b-title">{{ props.title || "" }}</div>
    <div ref="boxRef" class="flex-1 border-box p-24">
      <el-table
        ref="tableRef"
        :data="tableData"
        style="width: 100%"
        :height="height"
        :row-class-name="row => handleClassName(row)"
        header-row-class-name="kb-th"
        @mouseenter="toggleScroll(false)"
        @mouseleave="toggleScroll(true)"
      >
        <el-table-column
          v-for="item in columns"
          :key="item.prop"
          :prop="item.prop"
          :label="item.label"
          align="center"
        >
          <template #header>
            <div class="font-14">{{ item.label }}</div>
          </template>
          <template #default="scope">
            <div class="font-14">
              <div
                v-if="item.cellRenderer"
                v-html="
                  item.cellRenderer({ row: scope.row, index: scope.$index })
                "
              />
              <div v-else-if="item.formatter">
                {{ item.formatter(scope.row) }}
              </div>
              <div v-else>{{ scope.row[item.prop] }}</div>
            </div>
          </template>
        </el-table-column>
      </el-table>
    </div>
  </div>
</template>

<script lang="ts" scoped setup>
import { realWH } from "@/utils";
import { computed, onMounted, ref, onBeforeUnmount, watch } from "vue";

const props = defineProps({
  data: {
    type: Array,
    default: () => []
  },
  title: {
    type: String,
    default: ""
  },
  height: {
    type: [String, Number],
    default: 100
  },
  columns: {
    type: Array,
    default: () => []
  },
  rowClassName: {
    type: Function,
    default: (row: any) => ""
  },
  scrollSpeed: {
    // 新增：滚动速度（像素/帧），默认1
    type: Number,
    default: 1
  },
  frameInterval: {
    // 新增：滚动帧间隔（毫秒），默认30（约33帧/秒）
    type: Number,
    default: 40
  }
});

/* 处理行样式 */
const handleClassName = ({ row }) => {
  return (props.rowClassName?.(row) || "") + " kb-tr";
};

/* 列配置 */
const columns = computed(() => [...props.columns] as any);

/* 表格数据（含循环复制逻辑） */
const rawData = ref(props.data); // 原始数据（不修改）
const tableData = ref([...rawData.value]); // 渲染数据（可能包含复制的循环数据）
const isDataCopied = ref(false); // 是否已复制数据到末尾（避免重复复制）

// 监听原始数据变化，重置表格数据和滚动状态
watch(
  () => props.data,
  newVal => {
    rawData.value = newVal;
    tableData.value = [...newVal]; // 重置为新数据
    isDataCopied.value = false; // 重置复制状态
    resetScroll(); // 重置滚动位置
  },
  { deep: true } // 深度监听数组变化
);

/* 高度计算 */
const boxRef = ref<HTMLElement | null>(null);
const height = ref<string | number>(props.height);
onMounted(() => {
  if (boxRef.value) {
    // 容器高度 - 内边距（40px，通过realWH处理单位）
    height.value = boxRef.value.offsetHeight - realWH(40).w;
  }
});

/* 自动滚动核心逻辑 */
const tableRef = ref<any>(null);
let scrollFrame: number | null = null; // 动画帧ID
let lastScrollTime = 0; // 上次滚动时间（用于控制帧间隔）
const isScrolling = ref(false); // 是否正在滚动

// 获取表格滚动容器
const getScrollContainer = (): HTMLElement | null => {
  if (!tableRef.value) return null;
  const bodyWrapper = tableRef.value.$refs.bodyWrapper;
  return bodyWrapper?.getElementsByClassName(
    "el-scrollbar__wrap"
  )[0] as HTMLElement | null;
};

// 重置滚动位置到顶部
const resetScroll = () => {
  const container = getScrollContainer();
  if (container) container.scrollTop = 0;
};

// 检查是否需要滚动（内容高度 > 容器高度）
const needScroll = (): boolean => {
  const container = getScrollContainer();
  if (!container || !rawData.value.length) return false;
  return container.scrollHeight > container.clientHeight + 1; // 加1避免精度问题
};

// 滚动动画函数（使用requestAnimationFrame实现平滑效果）
const scrollAnimation = (timestamp: number) => {
  // 控制帧间隔（避免滚动过快）
  if (timestamp - lastScrollTime < props.frameInterval) {
    scrollFrame = requestAnimationFrame(scrollAnimation);
    return;
  }
  lastScrollTime = timestamp;

  const container = getScrollContainer();
  if (!container || !isScrolling.value) return;

  const { scrollTop, scrollHeight, clientHeight } = container;
  const rawDataLength = rawData.value.length;

  // 1. 当数据未复制且需要滚动时，复制一份原始数据到末尾（形成循环池）
  if (!isDataCopied.value && needScroll() && rawDataLength > 0) {
    tableData.value = [...rawData.value, ...rawData.value]; // 拼接原始数据
    isDataCopied.value = true;
  }

  // 2. 计算滚动距离（基于配置的速度）
  const newScrollTop = scrollTop + props.scrollSpeed;

  // 3. 无缝滚动核心：当滚动到复制数据区域时，重置到原始数据起点
  // 原始数据高度 ≈ 总高度的一半（因为tableData是原始数据*2）
  const rawDataScrollHeight = scrollHeight / 2;
  if (newScrollTop >= rawDataScrollHeight) {
    // 重置到顶部（视觉上无缝，因为前后数据一致）
    container.scrollTop = newScrollTop - rawDataScrollHeight;
  } else {
    container.scrollTop = newScrollTop;
  }

  // 继续下一帧动画
  scrollFrame = requestAnimationFrame(scrollAnimation);
};

// 切换滚动状态（启动/停止）
const toggleScroll = (start: boolean) => {
  if (start) {
    // 启动滚动（仅当需要滚动时）
    if (!needScroll() || isScrolling.value) return;
    isScrolling.value = true;
    lastScrollTime = 0;
    scrollFrame = requestAnimationFrame(scrollAnimation);
  } else {
    // 停止滚动
    if (!isScrolling.value) return;
    isScrolling.value = false;
    if (scrollFrame) {
      cancelAnimationFrame(scrollFrame);
      scrollFrame = null;
    }
  }
};

// 初始化滚动（组件挂载后1秒启动）
onMounted(() => {
  const timer = setTimeout(() => {
    if (needScroll()) {
      toggleScroll(true);
    }
  }, 1000);

  // 清理定时器
  onBeforeUnmount(() => clearTimeout(timer));
});

// 组件卸载时停止滚动
onBeforeUnmount(() => {
  toggleScroll(false);
});
</script>

<style lang="scss" scoped>
@import url(../table.scss);

// 可选：优化滚动条样式（隐藏默认滚动条，更美观）
::v-deep .el-scrollbar__wrap::-webkit-scrollbar {
  width: 0;
  height: 0;
}
::v-deep .el-scrollbar__wrap {
  scrollbar-width: none; // Firefox
  -ms-overflow-style: none; // IE/Edge
}
</style>
